﻿using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace FezLogForSns
{
    class TextChangingEventArgs : System.ComponentModel.CancelEventArgs
    {
        public TextChangingEventArgs()
        {
            this._ChangedText = string.Empty;
        }

        public TextChangingEventArgs(string text)
        {
            this._ChangedText = text;
        }

        private string _ChangedText;

        public string ChangedText
        {
            get { return this._ChangedText; }
        }
    }

    class ChangingTextBox : System.Windows.Forms.TextBox
    {
        /// <summary>入力により Text プロパティが変更される直前に発生します。</summary>
        [Category("プロパティ変更")]
        [Description("Text プロパティの値がコントロールで変更される直前に発生します。")]
        public event EventHandler<TextChangingEventArgs> TextChanging;
        protected virtual void OnTextChanging(TextChangingEventArgs e)
        {
            if (TextChanging != null)
            {
                TextChanging(this, e);
            }
        }

        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            const int WM_CHAR = 0x102;
            const int WM_PASTE = 0x302;

            switch (m.Msg)
            {
                case WM_CHAR:
                    {
                        // 制御文字は受け付ける
                        char c = (char)m.WParam.ToInt32();
                        if (char.IsControl(c) == true)
                        {
                            base.WndProc(ref m);
                            return;
                        }

                        // それ以外はイベント発生
                        TextChangingEventArgs e = new TextChangingEventArgs(this.CreateChangedText(Convert.ToString(c)));
                        this.OnTextChanging(e);
                        if (e.Cancel == true)
                        {
                            return;
                        }
                    }
                    break;

                case WM_PASTE:
                    {
                        // イベント発生
                        string clipText = (string)Clipboard.GetDataObject().GetData(DataFormats.Text);
                        if (clipText != null)
                        {
                            TextChangingEventArgs e = new TextChangingEventArgs(this.CreateChangedText(clipText));
                            this.OnTextChanging(e);
                            if (e.Cancel == true)
                            {
                                return;
                            }
                        }
                    }
                    break;
            }

            base.WndProc(ref m);
        }

        private string CreateChangedText(string inputText)
        {
            string changedText = this.Text;
            changedText = changedText.Remove(this.SelectionStart, this.SelectionLength);

            // 改行文字を貼り付け
            if (this.Multiline == false)
            {
                int crIndex = inputText.IndexOf("\r");
                if (crIndex > 0)
                {
                    inputText = inputText.Remove(crIndex);
                }

                int lrIndex = inputText.IndexOf("\n");
                if (lrIndex > 0)
                {
                    inputText = inputText.Remove(lrIndex);
                }
            }

            if (inputText == string.Empty)
            {
                return changedText;
            }

            // 入力文字と結合
            changedText = changedText.Insert(this.SelectionStart, inputText);

            return changedText;
        }
    }
}